package io.bdmc.core.msp2000;

import io.bdmc.common.utils.ByteUtil;
import io.bdmc.common.utils.Constant;
import io.bdmc.common.utils.StringUtils;
import io.bdmc.core.msp2000.model.EdfaSetting;
import io.bdmc.core.msp2000.model.FecSetting;
import io.bdmc.core.msp2000.model.SetFan;
import io.bdmc.modules.bss.entity.DeviceMachineFsp;
import io.bdmc.modules.bss.entity.DeviceMachineOsw;

/**
 * 下行数据组包 网管->设备
 */

public class DataBuild {

    /**
     * 轮询命令
     * 
     * @return FF00Msg
     */
    public static String buildFF00Msg() {
        return buildHeadMsg("FF00", "00000000", 5);
    }

    /**
     * 风扇盘设置指令
     * 
     * @param setFan 多个风扇盘设置信息
     * @return Str
     */
    public static String buildSetFanMsg(SetFan setFan) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(setFan.getSlotNum()));
        body.append("002F");
        body.append(setFan.getSn());
        body.append("0000");
        body.append("01");
        body.append("0022");
        body.append("0108");
        for (int i = 1; i < 9; i++) {
            if (setFan.getFanNum() == i) {
                String set = ByteUtil.intToHex_1(setFan.getMask()) + ByteUtil.intToHex_1(setFan.getFanMode())
                        + ByteUtil.intToHex_2(setFan.getFanRpm());
                body.append(set);
            } else {
                body.append("00000000");
            }
        }

        return buildHeadMsg("FF02", body.toString(), 5);
    }

    public static String buildSetFSPMsg(int slotNum, DeviceMachineFsp fsp) {
        return buildSetFSPMsg(slotNum, fsp.getDiskSn(), fsp.getWorkMode(), fsp.getLineType(),
                Integer.parseInt(fsp.getSwitchDelay()), Double.parseDouble(fsp.getTxAlarmThreshold()),
                Double.parseDouble(fsp.getT1AlarmThreshold()), Double.parseDouble(fsp.getT2AlarmThreshold()),
                Double.parseDouble(fsp.getRxAlarmThreshold()), Double.parseDouble(fsp.getR1AlarmThreshold()),
                Double.parseDouble(fsp.getR2AlarmThreshold()), Double.parseDouble(fsp.getR1SwitchThreshold()),
                Double.parseDouble(fsp.getR2SwitchThreshold()), 0, 0,
                (int) Double.parseDouble(fsp.getReturnTime()) * 10);

    }

    /**
     * 设置fsp指令
     */
    public static String buildSetFSPMsg(int slotNum, String sn, String workModel, String lineType, int delay, double tx,
            double t1, double t2, double rx, double r1, double r2, double r1Change, double r2Change, double tt,
            int change, int backTime) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(slotNum));
        body.append("002C");
        body.append(sn);
        body.append("0000");
        body.append("01");
        body.append("0021");
        body.append("03");
        body.append("EF");
        body.append("1E");
        body.append("20");
        body.append(workModel);
        body.append(lineType);
        body.append(ByteUtil.intToHex_1(delay / 4));
        body.append(doubleToHex(tx, 4));
        body.append(doubleToHex(t1, 4));
        body.append(doubleToHex(t2, 4));
        body.append(doubleToHex(rx, 4));
        body.append(doubleToHex(r1, 4));
        body.append(doubleToHex(r2, 4));
        body.append(doubleToHex(r1Change, 4));
        body.append(doubleToHex(r2Change, 4));
        body.append(doubleToHex(tt, 4));
        body.append("00DD");
        body.append(ByteUtil.intToHex_1(change));
        body.append(ByteUtil.intToHex_2(backTime));
        body.append("00AA");
        body.append(ByteUtil.makeChecksum(body.substring(30)));

        return buildHeadMsg("FF02", body.toString(), 3);
    }

    public static String doubleToHex(double d, int len) {
        String hex = Integer.toHexString((int) (d * 10)).toUpperCase();
        if (d >= 0) {
            return flushLeft('0', 4, hex);
        } else {
            return hex.substring(hex.length() - len);
        }

    }

    public static String flushLeft(char c, int length, String content) {
        String str;

        String cs = "";
        if (content.length() > length) {
            str = content;
        } else {
            for (int i = 0; i < length - content.length(); i++) {
                cs = cs + c;
            }
        }
        str = cs + content;
        return str;
    }

    public static String flushRigth(char c, int length, String content) {
        String str;

        String cs = "";
        if (content.length() > length) {
            str = content;
        } else {
            for (int i = 0; i < length - content.length(); i++) {
                cs = cs + c;
            }
        }
        str = content + cs;
        return str;
    }

    public static String buildSetEDFA(EdfaSetting edfa) {
        if (edfa.getMask() == 4) {
            return buildSetEdfaApcPower(edfa.getSn(), edfa.getGainValue() + "");
        }
        return buildSetEDFA(edfa.getSlotNum(), edfa.getSn(), edfa.getMask(), edfa.getInputThreshold(),
                edfa.getOutputThreshold(), edfa.getGainValue(), edfa.getWorkStatus());
    }

    /**
     * 设置edfa指令
     * 
     * @param slotNum         卡槽
     * @param sn              单盘序列号
     * @param mask            1：设置输入门限，2：设置输出门限，4：设置增益值，8：设置自动关泵，16：设置EDFA开关,24 设置状态
     * @param inputThreshold  设置输入门限
     * @param outputThreshold 设置输出门限
     * @param gainValue       设置增益值
     * @param workStatus      设置状态 00 强制关泵,01无光不关泵,11 无光关泵
     * @return HexString
     */
    public static String buildSetEDFA(int slotNum, String sn, int mask, double inputThreshold, double outputThreshold,
            double gainValue, String workStatus) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(slotNum));
        body.append("0015");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000a01");
        body.append(ByteUtil.intToHex_1(mask));
        body.append(ByteUtil.intToHex_2((int) (inputThreshold * 10)));
        body.append(ByteUtil.intToHex_2((int) (outputThreshold * 10)));
        body.append(ByteUtil.intToHex_2((int) (gainValue * 10)));
        if (StringUtils.isEmpty(workStatus)) {
            workStatus = "0000";
        }
        body.append(workStatus);
        // body.append(ByteUtil.intToHex_1(autoShutdown));
        // body.append(ByteUtil.intToHex_1(edfaSwitch));
        // body.append("000000"); //res
        return buildHeadMsg("FF02", body.toString(), 5);
    }

    public static String buildSetEdfaApcPower(String sn, String apcSet) {
        StringBuilder body = new StringBuilder();
        body.append("010019");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000e02");
        body.append("6d6f6465207020");
        body.append(ByteUtil.str2HexStr(apcSet));
        body.append("0d0a");
        return buildHeadMsg("FF02", body.toString(), 12);
    }

    /**
     * XFP或SFP单板进行模块认证命令
     * 
     * @param moduleNum 模块编号 0，1
     * @param randomKey 命令随机密码
     * @param password  模块设置密码
     * @param sn        设备sn
     * @return ModuleAuth STR
     */
    public static String buildModuleAuth(int moduleNum, int randomKey, String password, String sn) {
        StringBuilder body = new StringBuilder();
        body.append("EFEF110024");
        body.append(ByteUtil.intToHex_1(moduleNum));
        body.append(ByteUtil.intToHex_1(randomKey));
        body.append(password);
        body.append(sn);
        byte[] bs = ByteUtil.HexToBytes(body.toString());
        body.append(ByteUtil.intToHex_1(bs[11] + bs[7] + bs[6]));
        body.append(ByteUtil.intToHex_1((bs[12] + bs[8]) & bs[6]));
        body.append(ByteUtil.intToHex_1((bs[13] + bs[9]) | bs[6]));
        body.append(ByteUtil.intToHex_1((bs[14] + bs[10]) ^ bs[6]));
        body.append(ByteUtil.makeChecksum(body.toString()));

        return body.toString();

    }

    /**
     * XFP单板设置模块波长命令
     * 
     * @param slotAddr   单板槽位地址，采用调试单板设置时，其值为0
     * @param num        模块在单板中的编号
     * @param mode       模式
     * @param Wavelength 波长
     * @return HexString
     */
    public static String buildSetModuleWavelength(int slotAddr, int num, int mode, double Wavelength) {
        StringBuilder body = new StringBuilder();
        body.append("EFEF0E0096");
        body.append(ByteUtil.intToHex_1(slotAddr));
        body.append(ByteUtil.intToHex_1(num));
        body.append(ByteUtil.intToHex_1(mode));
        body.append(ByteUtil.intToHex_4((int) (Wavelength * 20)));
        body.append("00001011");
        body.append(ByteUtil.makeChecksum(body.toString()));
        return body.toString();
    }

    /**
     * 设置模块的无光关断模式及认证模式
     * 
     * @param type    21无光关断模式,20 认证模式
     * @param uchAddr 模块地址编号（对于4路的XFP单板，此值取值0-3）
     * @param mode    为1：表示模块无光LOS时激光器关断； 为0：表示模块无光LOS时激光器不关断|
     *                认证模式下：0认证关闭，1认证开启，2认证提示
     * @return HexString
     */
    public static String buildSetNoLightOffMode(String type, int slotNum, String sn, int uchAddr, int mode) {
        StringBuilder body = new StringBuilder();

        body.append(ByteUtil.intToHex_1(slotNum));
        body.append("0016");
        body.append(sn);
        body.append("0000"); // res
        body.append("01"); // CMDnum
        body.append("000B"); // 长度

        body.append("EFEF0800");
        body.append(type); // 21无光关断模式,20 认证模式
        body.append(ByteUtil.intToHex_1(uchAddr));
        body.append(ByteUtil.intToHex_1(mode));
        body.append("010203");
        body.append(ByteUtil.makeChecksum(body.toString()));

        return buildHeadMsg("FF02", body.toString(), 5);
    }

    /**
     * fec模块设置
     * 
     * @param fec 参数
     * @return 指令
     */
    public static String buildSetFECPara(FecSetting fec) {
        return buildSetFECPara(fec.getSlotNum(), fec.getSn(), fec.getOptType(), fec.getChannel(), fec.getDataType(),
                fec.getSetVal());
    }

    /**
     * fec模块设置
     * 
     * @param optType  0-6,0:FEC开启或关闭，1：设置FEC模式，2：单板硬件芯片软件自环，3：误码清零，4：FEC增益
     * @param channel  fec的通道号从0开始编号
     * @param dataType optType 0，1，4：无效；2：1,FEC单板硬件自环
     *                 0,fec芯片软件自环，3：0,当前误码清零，1,历史误码清零 2,全部误码清零
     * @param setVal   值
     * @return HexString
     */
    public static String buildSetFECPara(int slotNum, String sn, int optType, int channel, int dataType,
            String setVal) {

        StringBuilder body = new StringBuilder();

        body.append(ByteUtil.intToHex_1(slotNum));
        body.append("001A");
        body.append(sn);
        body.append("0000"); // res
        body.append("01"); // CMDnum
        body.append("000F"); // 长度

        body.append("EFEF");
        int dataLen = 1;
        if (optType == 5) {
            dataLen = setVal.length() / 2;
        }
        if (optType == 6) {
            dataLen = 2;
        }

        body.append(ByteUtil.intToHex_1(11 + dataLen));
        body.append("0010");
        body.append(ByteUtil.intToHex_1(optType));
        body.append("00");
        body.append(ByteUtil.intToHex_1(channel));
        body.append(ByteUtil.intToHex_1(dataType));
        body.append(ByteUtil.intToHex_1(dataLen));

        body.append(ByteUtil.intToHex_1(Integer.parseInt(setVal)));

        body.append("010203");
        body.append(ByteUtil.makeChecksum(body.substring(28)));

        return buildHeadMsg("FF02", body.toString(), 6);
    }

    /**
     * 1.RFA设置命令
     *
     * @param sn              出厂序列号
     * @param mask            1：设置输入门限，2：设置输出门限，4：设置增益值，
     * @param inputThreshold  输入门限
     * @param outputThreshold 输出门限
     * @param gainValue       增益值
     * @param autoShutdown    自动关泵 1-打开，0关闭
     * @param edfaSwitch      EDFA开关 1-打开，0-关闭
     * @return SetRFA STR
     */
    public static String buildSetRFA(String sn, int mask, double inputThreshold, double outputThreshold,
            double gainValue, int autoShutdown, int edfaSwitch) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0015");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000a01");
        body.append(ByteUtil.intToHex_1(mask));
        body.append(ByteUtil.intToHex_2((int) (inputThreshold * 10)));
        body.append(ByteUtil.intToHex_2((int) (outputThreshold * 10)));
        body.append(ByteUtil.intToHex_2((int) (gainValue * 10)));
        body.append(ByteUtil.intToHex_1(autoShutdown));
        body.append(ByteUtil.intToHex_1(edfaSwitch));
        // body.append("000000"); //res
        return buildHeadMsg("FF02", body.toString(), 6);
    }

    public static String buildSetRFA1(String sn, int mask, double inputThreshold, double outputThreshold,
            double gainValue, String workStatus) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0015");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000a01");
        body.append(ByteUtil.intToHex_1(mask));
        body.append(ByteUtil.intToHex_2((int) (inputThreshold * 10)));
        body.append(ByteUtil.intToHex_2((int) (outputThreshold * 10)));
        body.append(ByteUtil.intToHex_2((int) (gainValue * 10)));
        if (StringUtils.isEmpty(workStatus)) {
            workStatus = "0000";
        }
        body.append(workStatus);
        // body.append("000000"); //res
        return buildHeadMsg("FF02", body.toString(), 6);
    }

    /***
     * OPM设置波长
     * 
     * @param sn         SN
     * @param wavelength 波长范围
     * @return OPMWavelength STR
     */
    public static String buildSetOPMWavelength(String sn, String wavelength) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0019");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000E");

        body.append("EFEF000009110001230038");

        body.append(ByteUtil.makeChecksum(body.toString().substring(28)));
        body.append(wavelength);
        body.append(ByteUtil.makeChecksum(body.substring(28)));
        return buildHeadMsg("FF02", body.toString(), 7);
    }

    /**
     * OPM设置通道数
     */
    public static String buildSetOPMChannelNum(String sn, int channelNum) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0019");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000E");
        body.append("EFEF000009110001260032");
        body.append(ByteUtil.makeChecksum(body.substring(28)));
        body.append(ByteUtil.intToHex_1(channelNum));
        body.append(ByteUtil.makeChecksum(body.substring(28)));
        return buildHeadMsg("FF02", body.toString(), 13);
    }

    /**
     * 设置及读取OSW通道状态的命令
     * 
     * @param sn
     * @param optType 为0表示读取，为1表示设置
     * @param osw
     * @return
     */
    public static String buildSetOSW(String sn, int optType, DeviceMachineOsw osw) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0018");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000D");

        body.append("EFEF");
        if (optType == 1) {
            body.append(ByteUtil.intToHex_1(10));
        } else {
            body.append(ByteUtil.intToHex_1(4));
        }
        body.append("0092");
        body.append(ByteUtil.intToHex_1(optType));
        if (optType == 1) {
            body.append(ByteUtil.intToHex_2(4));
            body.append(ByteUtil.intToHex_1((int) (Double.parseDouble(osw.getHardwareVersion()) * 10)));
            body.append(ByteUtil.intToHex_1((int) (Double.parseDouble(osw.getProtocolVersion()) * 10)));
            int opticalSwitchType = Integer.parseInt(osw.getOpticalSwitchType());
            if (opticalSwitchType == 32) {
                body.append(ByteUtil.intToHex_1(3));
            } else {
                body.append(ByteUtil.intToHex_1(opticalSwitchType / 8));
            }

            body.append(ByteUtil.intToHex_1(Integer.parseInt(osw.getChannelState())));
        }
        body.append(ByteUtil.makeChecksum(body.substring(28)));
        return buildHeadMsg("FF02", body.toString(), 8);
    }

    /**
     * OS获取光源检测pin采样/功率值
     * 
     * @param sn    出厂序列号
     * @param value 0-获取采样值；1-获取功率值。
     * @return
     */
    public static String OSGetLightSourceDetection(String sn, int value) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0019");
        body.append(sn);
        body.append("0000"); // res
        body.append("010017");

        body.append("EFEF000009");
        body.append("110001300001");
        body.append(ByteUtil.makeChecksum(body.substring(28)));

        body.append(ByteUtil.intToHex_1(value));
        body.append(ByteUtil.makeChecksum(body.substring(28)));

        return buildHeadMsg("FF02", body.toString(), 12);
    }

    /**
     * OS开关光源
     * 
     * @param sn    出厂序列号
     * @param value 0-关闭光源；1-打开光源。
     * @return
     */
    public static String OSSwitchSource(String sn, int value) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0019");
        body.append(sn);
        body.append("0000"); // res
        body.append("010017");

        body.append("EFEF000009");
        body.append("110001310001");
        body.append(ByteUtil.makeChecksum(body.toString().substring(28)));

        body.append(ByteUtil.intToHex_1(value));
        body.append(ByteUtil.makeChecksum(body.toString().substring(28)));

        return buildHeadMsg("FF02", body.toString(), 13);
    }

    /**
     * OS设置波长和通道号
     * 
     * @param sn         出厂序列号
     * @param wavelength 波长
     * @return
     */
    public static String OSSetWavelengthChannel(String sn, String wavelength, int channelNum) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0022");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000E");

        body.append("EFEF000012110001320038");

        body.append(ByteUtil.makeChecksum(body.toString().substring(28)));
        body.append("01").append(ByteUtil.intToHex_1(channelNum));
        for (int i = 0; i < channelNum; i++) {
            body.append(wavelength);
        }
        body.append(ByteUtil.makeChecksum(body.substring(28)));
        return buildHeadMsg("FF02", body.toString(), 7);

    }

    public static String OSReadWavelengthChannel(String sn) {
        StringBuilder body = new StringBuilder();
        body.append(ByteUtil.intToHex_1(1));
        body.append("0019");
        body.append(sn);
        body.append("0000"); // res
        body.append("01000E");

        body.append("EFEF000009110001320037");

        body.append(ByteUtil.makeChecksum(body.toString().substring(28)));
        body.append("00");
        body.append(ByteUtil.makeChecksum(body.substring(28)));
        return buildHeadMsg("FF02", body.toString(), 7);
    }

    /**
     * 读电子标签
     */
    public static String buildFF01Msg() {
        return buildHeadMsg("FF01", "", 10);
    }

    public static String buildHeadMsg(String msgType, String body, int seq) {
        String retuString = "EFEF00" + ByteUtil.intToHex_2(body.length() / 2 + 8) + "11" + "00" + msgType
                + ByteUtil.intToHex_2(seq);
        retuString += ByteUtil.makeChecksum(retuString);
        retuString += body;
        retuString += ByteUtil.makeChecksum(retuString);
        return retuString.toUpperCase();
    }

    /**
     * 读取FMS盘参数指令
     */
    public static String readFMSPara(String slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "SPARA? 0";
        } else {
            return "O" + slotPort + " " + "SPARA? 0";
        }

    }

    /**
     * 设置FMS盘参数指令
     */
    public static String writeFMSPara(String slotPort, String range, String pulseWidth, String resolution, String model,
            String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "SPARA 0," + range + "," + pulseWidth + "," + resolution + "," + model;
        } else {
            return "O" + slotPort + " " + "SPARA 0," + range + "," + pulseWidth + "," + resolution + "," + model;
        }

    }

    /**
     * 设置fms测试时间
     * 
     * @param slotPort
     * @param time
     * @param deviceType
     * @return
     */

    public static String setFMSTestTime(Integer slotPort, Integer time, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "ACQT " + time;
        } else {
            return "O" + slotPort + " " + "ACQT " + time;
        }
    }

    /**
     * 设置fms用户光缆折射率
     * 
     * @param slotPort   卡槽号
     * @param refIndex   折射率
     * @param deviceType fms设备类型
     * @return 设备响应结果
     */
    public static String setFMSRefIndex(Integer slotPort, String refIndex, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "UIOR " + refIndex;
        } else {
            return "O" + slotPort + " " + "UIOR " + refIndex;
        }
    }

    /**
     * 读取fms测试时间
     * 
     * @param slotPort   卡槽号
     * @param deviceType 设备类型
     * @return 下发str
     */
    public static String readFMSTestTime(Integer slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "ACQT?";
        } else {
            return "O" + slotPort + " " + "ACQT?";
        }
    }

    /**
     * 读取fms用户光缆折射率
     * 
     * @param slotPort   卡槽号
     * @param deviceType 设备类型
     * @return
     */
    public static String readFMSRefIndex(Integer slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "UIOR?";
        } else {
            return "O" + slotPort + " " + "UIOR?";
        }
    }

    /**
     * FMS开始测试
     * 
     * @param slotPort   卡槽
     * @param deviceType 设备类型
     * @return 启动结果
     */
    public static String FMSStartTest(String slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "SCAN";
        } else {
            return "O" + slotPort + " " + "SCAN";
        }

    }

    /**
     * FMS读取状态
     * 
     * @param slotPort
     * @return
     */
    public static String FMSReadState(String slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "STATE?";
        } else {
            return "O" + slotPort + " " + "STATE?";
        }

    }

    /**
     * 获取Sor文件
     * 
     * @param slotPort   卡槽
     * @param deviceType 设备类型
     * @return sor
     */
    public static String FMSGetSor(String slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "GETSOR? 0";
        } else {
            return "O" + slotPort + " " + "GETSOR? 0";
        }
    }

    // 获取无线测量sor基本数据
    public static String FMSGetSorWireless(String slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "EVENT? TOP";
        } else {
            return "O" + slotPort + " " + "EVENT? TOP";
        }
    }

    public static String FMSGetSorEventWireless(String slotPort, Integer num, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "EVENT? LINE " + num;
        } else {
            return "O" + slotPort + " " + "EVENT? LINE " + num;
        }
    }

    /**
     * 设置反射阈值
     * 
     * @param slotPort
     * @param reflectance
     * @param deviceType
     * @return
     */
    public static String setFMSReflectanceThreshold(Integer slotPort, Integer reflectance, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "TREF 0 " + reflectance;
        } else {
            return "O" + slotPort + " " + "TREF 0 " + reflectance;
        }
    }

    /**
     * 读取反射阈值
     * 
     * @param slotPort
     * @param deviceType
     * @return
     */
    public static String readFMSReflectanceThreshold(Integer slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "TREF? 0";
        } else {
            return "O" + slotPort + " " + "TREF? 0";
        }
    }

    /**
     * 设置接头损耗阈值
     * 
     * @param slotPort
     * @param threshold
     * @param deviceType
     * @return
     */
    public static String setFMSSpliceLossThreshold(Integer slotPort, String threshold, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "TLOS 0 " + threshold;
        } else {
            return "O" + slotPort + " " + "TLOS 0 " + threshold;
        }
    }

    /**
     * 读取接头损耗阈值
     * 
     * @param slotPort
     * @param deviceType
     * @return
     */
    public static String readFMSSpliceLossThreshold(Integer slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "TLOS? 0";
        } else {
            return "O" + slotPort + " " + "TLOS? 0";
        }
    }

    /**
     * 设置光纤终端阈值
     * 
     * @param slotPort
     * @param threshold
     * @param deviceType
     * @return
     */
    public static String setFMSEndOfFiberThreshold(Integer slotPort, String threshold, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "TEOF 0 " + threshold;
        } else {
            return "O" + slotPort + " " + "TEOF 0 " + threshold;
        }
    }

    /**
     * 读取光纤终端阈值
     * 
     * @param slotPort
     * @param deviceType
     * @return
     */
    public static String readFMSEndOfFiberThreshold(Integer slotPort, String deviceType) {
        if (deviceType.equals(Constant.FMSM) || deviceType.equals(Constant.FMSA)) {
            return "TEOF? 0";
        } else {
            return "O" + slotPort + " " + "TEOF? 0";
        }
    }

    /**
     * 1U设备读取所有设备信息
     * 
     * @return
     */
    public static String build0401Msg() {
        return buildHeadMsg("0401", "", 10);
    }

    public static String buildFecHeadMsg(String cmd, String body) {
        String retuString = "EFEF" + ByteUtil.intToHex_1(body.length() / 2 + 3) + "FF" + cmd + body;
        retuString += ByteUtil.makeChecksum(retuString);

        return retuString.toUpperCase();
    }

    /**
     * 串口控制FEC开关命令
     * 
     * @param offOrOn 1 表示开启FEC功能。0 表示关掉FEC功能。
     * @return
     */
    public static String buildSetFecOffOn(int offOrOn) {
        return buildFecHeadMsg("02", ByteUtil.intToHex_1(offOrOn));
    }

    /**
     * 串口设置FEC线路侧和客户侧的衰耗器值的命令
     * 
     * @param channel     取值0-3，分别表示Client Rx、Client Tx、Line Rx和Line Tx处添加衰耗器。
     * @param attenuation 为设置的衰耗器的
     * @return
     */
    public static String buildSetFecAttenuation(int channel, int attenuation) {

        return buildFecHeadMsg("09", ByteUtil.intToHex_1(channel) + ByteUtil.intToHex_1(attenuation));
    }

    /**
     * 串口设置FEC的内部自环状态的命令
     * 
     * @param channel    取值0-3，分别表示Client Rx、Client Tx、Line Rx和Line Tx处添加衰耗器。
     * @param loopStatus 设置的自环状态，取0表示关闭自环，取1表示开启自环
     * @return
     */
    public static String buildSetFecSelfLoopState(int channel, int loopStatus) {
        return buildFecHeadMsg("0A", ByteUtil.intToHex_1(channel) + ByteUtil.intToHex_1(loopStatus));
    }

    /**
     * 串口设置FEC的外部S4815芯片自环状态的命令
     * 
     * @param channel 取值为1-4，分别表示设置Line Rx from Line Tx，Line Tx from Line Rx, Client
     *                Rx from Client Tx, Client Tx from Client Rx自环
     * @param status  0，设置为自环模式；1，关闭自环
     * @return
     */
    public static String buildSetFecChipState(int channel, int status) {
        return buildFecHeadMsg("0B", ByteUtil.intToHex_1(channel) + ByteUtil.intToHex_1(status));
    }

    public static String buildSetFecDebugCmd(int mdAddr, String cmd, String txData) {

        StringBuilder body = new StringBuilder();
        body.append("00");
        body.append(ByteUtil.intToHex_1(mdAddr));
        body.append(cmd);

        int rxLen = 0;
        switch (cmd.toUpperCase()) {
            case "C7":
            case "4A":
                rxLen = 6;
                break;
            case "C3":
            case "C6":
            case "C1":
            case "49":
                rxLen = 3;
                break;
            case "F3":
                rxLen = 5;
                break;
            case "F0":
                rxLen = 7;
                break;
        }

        body.append(ByteUtil.intToHex_1(txData.length()));
        body.append(ByteUtil.intToHex_1(rxLen));
        body.append(txData);

        return buildFecHeadMsg("92", body.toString());
    }

    public static String buildRadFspOlpCmd(String code) {

        StringBuilder cmd = new StringBuilder();
        cmd.append("EFEF03");
        cmd.append(code);
        cmd.append("00");
        cmd.append(ByteUtil.makeChecksum(cmd.toString()));

        return cmd.toString();
    }

    public static String buildSetFspOlpCmd(DeviceMachineFsp fsp) {

        StringBuilder body = new StringBuilder();
        body.append("EFEF242001");
        body.append(ByteUtil.makeChecksum(body.toString()));
        body.append(ByteUtil.intToHex_1(fsp.getSingleSlot()));
        body.append(fsp.getWorkMode());
        body.append(fsp.getLineType());
        body.append(ByteUtil.intToHex_1(Integer.parseInt(fsp.getSwitchDelay()) / 4));
        body.append(doubleToHex(Double.parseDouble(fsp.getTxPower()), 4));
        body.append(doubleToHex(Double.parseDouble(fsp.getT1Power()), 4));
        body.append(doubleToHex(Double.parseDouble(fsp.getT2Power()), 4));
        body.append(doubleToHex(Double.parseDouble(fsp.getRxPower()), 4));
        body.append(doubleToHex(Double.parseDouble(fsp.getR1Power()), 4));
        body.append(doubleToHex(Double.parseDouble(fsp.getR2Power()), 4));
        body.append(doubleToHex(Double.parseDouble(fsp.getR1SwitchThreshold()), 4));
        body.append(doubleToHex(Double.parseDouble(fsp.getR2SwitchThreshold()), 4));
        body.append("00000000AA");
        body.append(ByteUtil.intToHex_2((int) Double.parseDouble(fsp.getReturnTime()) * 10));
        body.append("00AA");
        body.append(fsp.getDeviceSN());
        body.append(ByteUtil.makeChecksum(body.toString()));

        return body.toString();
    }

    public static String buildSetFspOlpSwitchLine(DeviceMachineFsp fsp) {

        return buildSetFspOlpCmd(fsp);
    }

}